import { APlugin } from '../types/common.interface';
import { TableDatas } from '../cors/table-datas';
import { Inject, Injectable, PluginInjectable } from '../decorators/inject';
import { Select } from '../cors/select';
import { ExecuteRecord } from '../cors/execute-record';
import { Hook } from '../cors/hook';
import { RowHeightCommand } from '../commands/row-height-command';
import { NExcel } from '../types';
import { Config } from '../cors/config';
import { createElement } from '../utils/dom-helper';
import { fromEvent } from 'rxjs';
import { filter } from 'rxjs/operators';
import './row-height.plugin.less';
import { EventHelper } from '../utils/event-helper';
import { RenderTrigger } from '../cors/render-trigger';
import { Cache } from '../cors/cache';

@Injectable()
@PluginInjectable('RowHeightPlugin')
export class RowHeightPlugin  extends APlugin{
    protected isEffectHover: boolean = true;
    protected lineEle: HTMLElement;
    protected referenceLine: HTMLElement;
    protected disableChangeHeight: boolean = true;
    constructor(
        @Inject(NExcel.OperateContainerToken) protected ele: HTMLElement,
        protected conf: Config,
        protected datas: TableDatas,
        protected executeRecord: ExecuteRecord,
        protected renderTrigger: RenderTrigger,
        protected hook: Hook,
        protected cache: Cache
    ) {
        super();
    }
    public init() {
        let ele = createElement('div', 'z-table-set-height');
        ele.style.width = this.conf.header.row.width / this.conf.pixelRatio + 'px';
        ele.style.display = 'none';
        let child = createElement('div', 'child');
        child.style.left = this.conf.header.row.width / this.conf.pixelRatio + 'px';
        child.style.width = String(this.ele.clientWidth - this.conf.header.row.width / this.conf.pixelRatio) + 'px';
        ele.appendChild(child);
        this.lineEle = ele;
        this.referenceLine = child;
        this.ele.appendChild(ele);
        this.showLine();
        this.bindChangeRowHeightEvent();
    }
    protected showLine() {
        fromEvent<MouseEvent>(this.ele, 'mousemove')
        .pipe(filter((evt: MouseEvent) => {
            if(this.isEffectHover == false) {
                return false;
            }
            if(evt.offsetX > (this.conf.header.row.width) || evt.offsetX < 1) {
                this.lineEle.style.display = 'none';
                this.ele.style.cursor = 'default';
                return false;
            }
            if(evt.offsetY < (this.conf.header.col.height - 1 * this.conf.enlarge)) {
                this.lineEle.style.display = 'none';
                this.ele.style.cursor = 'default';
                return false;
            }
            return true;
        }))
        .subscribe(evt => {
            let isHover = false;
            const hoverY = evt.offsetY * this.conf.pixelRatio;
            let hoverRow = this.cache.getPointRow(hoverY);
            let [_, endY] = this.cache.getRowPositon(hoverRow);
            if(hoverY > endY - 3 * this.conf.pixelRatio) {
                let total = endY / this.conf.pixelRatio + 1;
                this.ele.style.cursor = 'row-resize';
                this.lineEle.style.top = total-2 + 'px';
                this.lineEle.style.display = 'block';
                this.lineEle.style.cursor = 'row-resize';
                isHover = true;
            } else {
                this.ele.style.cursor = 'default';
                this.lineEle.style.cursor = 'default';
                this.lineEle.style.display = 'none';
            }
        });
    }
    protected bindChangeRowHeightEvent() {
        EventHelper.move(
            this.lineEle,
            (evt: MouseEvent) => {
                this.isEffectHover = false;
                this.referenceLine.style.display = 'block';
                let row = this.getClickRow(evt);
                let top = Number(this.lineEle.style.top.replace('px', ''));
                return {x: evt.clientY, y: evt.clientY, row: row, top: top}
            },
            (evt: MouseEvent, param: {x: number, y: number, row: number, top: number}) => {
                let moveY = evt.clientY - param.y;
                let rowHeight = (this.datas.getRowHeight(param.row) / this.conf.pixelRatio / this.conf.scale) + moveY;
                let setHeight = rowHeight > 3 ? rowHeight : 3;
                let command  = new RowHeightCommand(this.datas, this.renderTrigger, param.row, setHeight);
                this.executeRecord.execute(command);
                this.isEffectHover = true;
                this.lineEle.style.display = 'none';
                this.referenceLine.style.display = 'none';
            },
            (param: {x: number, y: number, row: number, top: number}, evt: MouseEvent) => {
                let moveY = evt.clientY - param.y;
                this.lineEle.style.top = String(moveY + param.top) + 'px';
                return moveY;
            }
        )
    }
    protected getClickRow(evt: MouseEvent) {
        let top = Number(this.lineEle.style.top.replace('px', '')) * this.conf.pixelRatio - 1;
        let hoverRow = this.cache.getPointRow(top);
        return hoverRow;
    }
    public destroy() {

    }
}